# -*- coding: utf-8 -*-
import csv
import json
from ftplib import error_perm
from wt.connector.db_manager.db_untils_tools import DBUntilsTools
import datetime
from wt.connector import data_connect
import os
import shutil


class HdfsExec(data_connect.DataConnect, DBUntilsTools):
    def __init__(self, ):
        super().__init__()
        self.buffer_size = 2048

    def general_col_value(self):
        """
        生成 ftpFile数据
        :return:
        """
        data = []
        for i in range(1, 1001):
            record = {
                "int_col": i,
                "c_02_integer_val": self.get_random(-2147483648, 2147483648),
                "c_03_double_val": self.get_random_float(-500, 500),
                "c_04_float_val": self.get_random_float(-500, 500),
                "c_05_smallint_val": self.get_random(-32768, 32767),
                "c_06_bigint_val": self.get_random(-9223372036854775808, 9223372036854775807),
                "c_07_tinyint_val": self.get_random(-128, 123),
                "c_08_decimal_val": self.get_random_float(-500, 500),
                "c_09_varchar_val": self.get_random_string(8),
                "c_10_date_val": self.get_random_date(),
                "c_11_datetime_val": self.get_random_datetime()
            }
            data.append(record)
        return data

    def generate_file(self, table, text_type):
        """
        根据不同的文件类型在本地生成不同的文件
        :param text_type: 文件类型
        :param table: 文件名称
        """
        data = self.general_col_value()

        file_path = "../resources/file/ftpfile/{}/{}.{}".format(table, table, text_type)
        path = "../resources/file/ftpfile/{}".format(table)

        try:
            os.makedirs(path, exist_ok=True)

            # 根据传入的text_type生成不同的文件内容
            if text_type == "csv":
                fieldnames = data[0].keys()
                with open(file_path, 'w', newline='', encoding='utf-8') as csvfile:
                    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
                    writer.writeheader()
                    writer.writerows(data)
                return True
            elif text_type == "text":
                fieldnames = data[0].keys()
                with open(file_path, 'w', encoding='utf-8') as txtfile:
                    txtfile.write(','.join(fieldnames) + '\n')
                    for row in data:
                        txtfile.write(','.join(map(str, row.values())) + '\n')
                return True
            elif text_type == "json":
                with open(file_path, 'w', encoding='utf-8') as jsonfile:
                    json.dump(data, jsonfile, ensure_ascii=False, indent=4)
                print(f"file_path: {file_path}")
                return True
            else:
                return False
        except Exception as e:
            print(f"An error occurred: {e}")

    def clear_server_folder(self, tableName):
        """
        逐层删除指定目录及其所有内容
        :param tableName: 表名
        """
        ftp = self.get_ftp_server()
        path = "/data/vsftp_path/wt_file/{}/".format(tableName)

        # 确保路径以 '/' 结尾
        if not path.endswith('/'):
            path += '/'

        try:
            # 获取目录中的所有文件和子目录
            items = ftp.nlst(path)
            stack = [path]  # 使用栈来模拟递归过程

            while stack:
                current_path = stack.pop()
                items = ftp.nlst(current_path)

                for item in items:
                    fullpath = current_path + item
                    # 跳过 '.' 和 '..' 目录
                    if item in ['.', '..']:
                        continue
                    try:
                        # 尝试将当前路径切换为文件，删除文件
                        ftp.delete(fullpath)
                        print(f"Deleted file: {fullpath}")
                    except error_perm:
                        # 如果无法删除文件，将其切换为目录并将子目录入栈
                        ftp.cwd(fullpath)
                        stack.append(fullpath + '/')
                # 删除空目录
                ftp.rmd(current_path)
                print(f"Deleted directory: {current_path}")

            return True
        except error_perm as e:
            print(f"Error deleting directory {path}: {e}")
            if "550" in str(e):
                print("Permission denied or directory does not exist.")
            return False

    def clear_folder(self, table):
        """
        清空指定文件夹中的所有文件和子文件夹
        :param table: 文件夹的路径
        """
        try:
            folder_path = "../resources/file/ftpfile/{}".format(table)

            # 确保目标文件夹存在
            if os.path.exists(folder_path):
                # 遍历文件夹中的所有文件和子文件夹
                for filename in os.listdir(folder_path):
                    file_path = os.path.join(folder_path, filename)
                    # 如果是文件，则直接删除
                    if os.path.isfile(file_path):
                        os.remove(file_path)
                    # 如果是文件夹，则递归清空文件夹
                    elif os.path.isdir(file_path):
                        shutil.rmtree(file_path)
                return True
            else:
                print(f"文件夹 {folder_path} 不存在")
                return False
        except Exception as e:
            print(f"An error occurred: {e}")
            return False

    def download_latest_file(self, tableName):
        """
        从 ftp 下载文件 只拿最新日期的文件
        :param tableName:
        :return:
        """
        ftp = self.get_ftp_server()

        try:
            remote_path = "/data/vsftp_path/wt_file/{}/".format(tableName)
            local_path = "../resources/file/ftpfile/{}/".format(tableName)

            os.makedirs(local_path, exist_ok=True)

            ftp.cwd(remote_path)

            file_list_with_date = []
            ftp.retrlines('LIST', file_list_with_date.append)

            file_list = []
            file_dates = {}
            for line in file_list_with_date:
                items = line.split()
                filename = items[-1]
                file_list.append(filename)
                file_date_str = ' '.join(items[-4:-1])
                file_date = datetime.datetime.strptime(file_date_str, "%b %d %H:%M")
                file_dates[filename] = file_date

            newest_file = max(file_dates, key=file_dates.get)
            local_filename = os.path.join(local_path, newest_file)
            with open(local_filename, 'wb') as f:
                ftp.retrbinary('RETR ' + newest_file, f.write)
            return True
        except Exception as e:
            print(f"An error occurred: {e}")
            return False

    def ensure_directory(self, ftp, path):
        """确保目录存在，如果不存在则创建目录"""
        dirs = path.split('/')
        current_path = ''
        for dir in dirs:
            if dir:
                current_path += '/' + dir
                try:
                    ftp.cwd(current_path)
                except error_perm:
                    try:
                        ftp.mkd(current_path)
                        ftp.cwd(current_path)
                    except error_perm as e:
                        print(f'Error creating directory {current_path}: {e}')
                        raise

    def upload_file(self, tableName, text_type):
        """
        从本地上传文件到 ftp
        :param text_type:
        :param tableName:
        :return: None
        """
        try:
            ftp = self.get_ftp_server()

            remote_path = "/data/vsftp_path/wt_file/{}/".format(tableName)
            local_path = "../resources/file/ftpfile/{}/{}.{}".format(tableName, tableName, text_type)

            # Ensure remote_path is treated as a directory
            remote_dir = remote_path if remote_path.endswith('/') else remote_path + '/'
            filename = local_path.split('/')[-1]
            remote_file_path = remote_dir + filename

            self.ensure_directory(ftp, remote_dir)

            with open(local_path, 'rb') as fp:
                print(f"Uploading {local_path} to {remote_file_path}")
                ftp.storbinary('STOR ' + remote_file_path, fp, self.buffer_size)
                ftp.set_debuglevel(0)
            return True
        except Exception as e:
            print(f"An error occurred: {e}")
            return False

    def path_list(self, path: str) -> list:
        """
        获取ftp服务器指定路径下的全部信息
        :param path: 路径
        :return:
        """
        ftp = self.get_ftp_server()

        # 切换路径
        ftp.cwd(path)
        # 获取目录下的文件夹
        dir_list: list = ftp.nlst()
        # 排序
        dir_list.sort()
        return dir_list

    def get_files_in_directory(self, directory):
        """
        获取指定目录下的所有文件
        :param directory: 目录路径
        :return: 文件列表
        """
        files_list = []
        # 遍历目录中的所有文件和子文件夹
        for root, dirs, files in os.walk(directory):
            for file in files:
                file_path = os.path.join(root, file)
                files_list.append(file_path)
        return files_list

    def get_file_count(self, tableName):
        """
        获取文件夹中的条数
        :param text_type:
        :param tableName:
        :return:
        """
        local_path = "../resources/file/ftpfile/{}/".format(tableName)

        files_path = self.get_files_in_directory(local_path)[0]

        file_type = files_path.split('.')[-1]
        if file_type == "json":
            with open(files_path, 'r', encoding='utf-8') as file:
                data = json.load(file)

                if isinstance(data, list):
                    return len(data)
                elif isinstance(data, dict):
                    return len(data.keys())
        else:
            with open(files_path, 'r', encoding='utf-8') as file:
                line_count = sum(1 for line in file)
            return line_count


if __name__ == '__main__':
    ftp = FtpExec()
    ftp.generate_file("FtpFile_to_mysql", "json")
    # ftp.upload_file("FtpFile_to_mysql", "json")
    # print(ftp.clear_folder("test1"))
    # ftp.upload_file("/data/vsftp_path/wt_file/test1/", "../../resources/file/ftpfile/test1/test1.csv")
    # # ftp.generate_file("TEXT", "test1")
    # file_list = ftp.ftp_path_list("/data/vsftp_path/wls_file/ftp")
    # # asd = ftp.get_file_count("../file/qwe.csv")
    # file = ""
    # local_path = ""
    # for i in file_list:
    #     file = "/data/vsftp_path/wls_file/ftp/" + i
    #     local_path = "../file/ftpfile/" + i
    # ftp.ftp_clear_folder(local_path)
    # ftp.ftp_download_file(file, local_path)
